package org.easy.socket.client;

import cn.hutool.core.date.DateUtil;
import org.easy.socket.client.config.ClientConfig;
import org.easy.socket.client.mamager.IOperator;
import org.easy.socket.client.plugin.ReconnectPlugin;
import org.easy.socket.client.processor.EasyClientMessageProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smartboot.socket.extension.protocol.StringProtocol;
import org.smartboot.socket.transport.AioQuickClient;
import org.smartboot.socket.transport.AioSession;
import org.smartboot.socket.transport.WriteBuffer;

import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

/**
 * @Description: TCP SOCKET 客户端
 * @Author: wxl
 * @CreateTime: 2023/1/12 10:24
 */
public final class EasyClient implements IOperator{

    private final static Logger logger = LoggerFactory.getLogger(EasyClient.class);

    private ClientConfig config;

    private AioQuickClient client;

    private AioSession session;

    private boolean status;

    private boolean startHeart;

    /**
     * 是否开启断开重连，默认为true
     */
    private boolean reConnected;

    private final EasyClientMessageProcessor processor;

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);

    public EasyClient (ClientConfig config) {
        this.config = config;
        this.reConnected = true;
        this.processor = new EasyClientMessageProcessor();
    }


    /**
     * 启动
     */
    @Override
    public void start() {
        if (Objects.isNull(client)) {
            this.setClientOption();
        } else {
            if (!status && Objects.isNull(this.session)) {
                this.client = null;
                this.setClientOption();
            }
        }
    }

    /**
     * 获取写入缓冲区
     *
     * @return WriteBuffer
     */
    @Override
    public WriteBuffer getWriteBuffer() {
        return getSession().writeBuffer();
    }

    /**
     * 设置会话
     *
     * @param session 会话
     */
    @Override
    public void setSession(AioSession session) {
        this.session = session;
    }

    /**
     * 获取会话
     *
     * @return AioSession
     */
    @Override
    public AioSession getSession() {
        return this.session;
    }

    /**
     * 创建AioQuickClient
     *
     * @return AioQuickClient
     */
    @Override
    public AioQuickClient create() {
        AioQuickClient client =  new AioQuickClient(getConfig().getHost(), getConfig().getPort(), new StringProtocol(), getProcessor());
        ReconnectPlugin reconnectPlugin = new ReconnectPlugin(client);
        this.processor.addPlugin(reconnectPlugin);
        return client;
    }

    /**
     * 发送数据
     *
     * @param data 数据
     */
    @Override
    public void send(String data) {
        if (status) {
            getProcessor().sendToServer(data);
        }
    }

    /**
     * 设置是否开启心跳
     *
     * @param flag 是否开启
     */
    @Override
    public void setStartHeart(boolean flag) {
        this.startHeart = flag;
    }

    /**
     * 设置开启重连
     *
     * @param flag 是否开启
     */
    @Override
    public void setReConnected(boolean flag) {
        this.reConnected = flag;
    }

    /**
     * 关闭
     */
    @Override
    public void close() {
        this.session.close();
        this.session = null;
        this.status = false;
    }

    private void setClientOption(){
        this.client = this.create();
        try {
            AioSession session = this.client.start();
            addListener();
            setSession(session);
            this.status = true;
        } catch (IOException e) {
            this.status = false;
            logger.error("于[{}]开启客户端异常:{}",DateUtil.now(),e.getMessage());
        }
    }

    private void addListener () {
        if (this.startHeart) {
            this.addHeartListener();
        }
        if (this.reConnected) {
            this.addReConnectedListener();
        }
    }

    private void addHeartListener(){

    }

    private void addReConnectedListener(){
        if (Objects.isNull(this.session)) {

        }
    }

    public ClientConfig getConfig() {
        return config;
    }

    public void setConfig(ClientConfig config) {
        this.config = config;
    }

    public AioQuickClient getClient() {
        return client;
    }

    public EasyClientMessageProcessor getProcessor() {
        return processor;
    }
}
